#include "../StdInc.h"

namespace GSTrader
{
	namespace Indicator
	{
		StdDev::StdDev()
		{
			m_strIndicatorName = "StdDev";
			m_n = 0;
			m_nBarType = bdtClose;
		}

		StdDev::StdDev(CSeries* pInput, int n, int nBarType)
		{
			m_pInput = pInput;
			m_n = n;
			m_nBarType = nBarType;
			RefreshData();
		}


		StdDev::~StdDev()
		{
		}

		CIndicator* StdDev::CreateInstance()
		{
			return new StdDev;
		}

		double StdDev::Calculate(int nIndex)
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0 || m_n <= 0)
				return 0;

			int nCount = m_pInput->GetCount();
			int nStartIndex = m_pInput->m_nStartIndex + nIndex - m_n + 1;
			if (nStartIndex < 0 || nStartIndex >= nCount)
				return 0;

			double dValue = 0, d2 = 0;

			int x;
			for (x = 0; x < m_n; x++)
			{
				dValue += m_pInput->GetValue(nIndex - x, m_nBarType);
			}

			dValue /= m_n;
			for (x = 0; x < m_n; x++)
			{
				double d3 = m_pInput->GetValue(nIndex - x, m_nBarType);
				d2 += (d3 - dValue) * (d3 - dValue);	
			}

			int nCycle = (m_n - 1);
			if (nCycle == 0)
			{
				return 0;
			}

			dValue = sqrt(d2 / nCycle);
			m_pResult->SetValue(nIndex, dValue);
			
			return dValue;
		}

		void StdDev::SetParam(int n, int nBarType)
		{
			m_n = n;
			m_nBarType = nBarType;

			RefreshData();
		}

		void StdDev::SetParam(double* pdParam)
		{
			if (pdParam)
			{
				m_n = (int)pdParam[0];
				m_nBarType = (int)pdParam[1];
			}

			RefreshData();
		}

		void StdDev::RefreshData()
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0 || m_n <= 1)
			{ 
				m_pResult->m_pDataSeries->m_nStartIndex = -1;
				return;
			}

			int nCount = m_pInput->GetCount();
			int nStartIndex = m_n - 1;

			m_pResult->m_pDataSeries->SetSize(nCount, nStartIndex);
			m_bCalc = true;
		}
	}
}
